#include "TextBlock.h"
#include "UIControlDes.h"
#include "UIStyle.h"
#include "TextLine.h"
#include <EIKENV.H>
#include <COEMAIN.H>
#include <GRDSTD.H>

TextStyle::TextStyle() :iFont(NULL),
						iFontName(_L("Annotation")),
						iFontSize(_L("normal")),
						iColor(0,0,0),
						iBackColor(255,255,255),
						iBold(EFalse),
						iItalic(EFalse),
						iRef(0)
{

}

TextStyle::~TextStyle()
{
	CEikonEnv::Static()->ScreenDevice()->ReleaseFont(iFont);
}

void TextStyle::AddRef()
	{
	iRef++;
	}

void TextStyle::RemoveRef()
	{
	iRef--;
	if(iRef <= 0)
		delete this;
	}

void TextStyle::SetPropertyL(const TDesC& aProperty,const TDesC& aValue)
	{
	if(aProperty.Compare(KTextStyleFont) == 0)
		{
		iFontName.Copy(aValue);
		}
	else if(aProperty.Compare(KTextStyleFontSize) == 0)
		{
		iFontSize.Copy(aValue);
		}
	else if(aProperty.Compare(KTextStyleColor) == 0)
		{
		UIColor color;
		color = aValue;
		iColor = color.GetColor();
		}
	else if(aProperty.Compare(KTextStyleBackColor) == 0)
		{
		UIColor color;
		color = aValue;
		iBackColor = color.GetColor();
		}
	else if(aProperty.Compare(KTextStyleBold) == 0)
		{
		if(aValue.Compare(_L("true")) == 0)
			iBold = ETrue;
		else
			iBold = EFalse;
		}
	else if(aProperty.Compare(KTextStyleItalic) == 0)
		{
		if(aValue.Compare(_L("true")) == 0)
			iItalic = ETrue;
		else
			iItalic = EFalse;
		}
	}

void TextStyle::SetPropertyL(const TDesC8& aProperty,const TDesC8& aValue)
	{
	TBuf<UIControl_Attribute_MaxLength> bufProp;
	bufProp.Copy(aProperty);
	TBufC<UIControl_Attribute_MaxLength> bufPropC(bufProp);
	
	TBuf<UIControl_Value_MaxLength> bufVal;
	bufVal.Copy(aValue);
	TBufC<UIControl_Value_MaxLength> bufValC(bufVal);
	
	SetPropertyL(bufPropC,bufValC);
	
	}
/////////////////////////////////////////////////////////
CTextBlock::CTextBlock()
{
}

CTextBlock::~CTextBlock()
{
	iTextStyle->RemoveRef();
	
	delete iText;
	iText = NULL;
}

CTextBlock* CTextBlock::NewL(const TDesC& aDes)
{
	CTextBlock* self = CTextBlock::NewLC(aDes);
	CleanupStack::Pop(self);
	
	return self;
}

CTextBlock* CTextBlock::NewLC(const TDesC& aDes)
{
	CTextBlock* self = new(ELeave) CTextBlock;
	CleanupStack::PushL(self);
	self->ConstructL(aDes);
	
	return self;
}

void CTextBlock::ConstructL(const TDesC& aDes)
{
	iText = HBufC::NewL(aDes.Length());
	CleanupStack::PushL(iText);
	TPtr ptr = iText->Des();
	
	ptr.Copy(aDes);
	CleanupStack::Pop(1);
	
	TInt tt = aDes.Length();

}

void CTextBlock::EstimateSize()
	{
	
	}

void CTextBlock::Draw(CGraphicsContext* aGc)
	{
	if(!iTextStyle->iFont)
		{
		CreateFontSpecByStyleL();
		CEikonEnv::Static()->ScreenDevice()->GetNearestFontInTwips( iTextStyle->iFont, iTextStyle->iFontSpec );
		}
	
	aGc->UseFont(iTextStyle->iFont);

	//设置颜色
	aGc->SetPenColor(iTextStyle->iColor);
	//画背景
//	aGc->SetBrushColor(iTextStyle->iBackColor);
//	aGc->DrawRect(iBlockRect);
	TGridUtils::FillRect(aGc,iTextStyle->iBackColor,iBlockRect);
	
	//DrawText
	aGc->DrawText(*iText,iBlockRect,iTextStyle->iFont->FontMaxAscent());
		
	aGc->DiscardFont();
	}

void CTextBlock::CreateFontSpecByStyleL()
	{

	if(iTextStyle->iFontName == KFontAnnotation)
		iTextStyle->iFontSpec = CEikonEnv::Static()->AnnotationFont()->FontSpecInTwips();
	else if(iTextStyle->iFontName == KFontTitle)
		iTextStyle->iFontSpec = CEikonEnv::Static()->TitleFont()->FontSpecInTwips();
	else if(iTextStyle->iFontName == KFontLegend)
		iTextStyle->iFontSpec = CEikonEnv::Static()->LegendFont()->FontSpecInTwips();
	else if(iTextStyle->iFontName == KFontSymbol)
		iTextStyle->iFontSpec = CEikonEnv::Static()->SymbolFont()->FontSpecInTwips();
	else if(iTextStyle->iFontName == KFontDense)
		iTextStyle->iFontSpec = CEikonEnv::Static()->DenseFont()->FontSpecInTwips();
	
	if(iTextStyle->iBold)
		iTextStyle->iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
	else
		iTextStyle->iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
	
	if(iTextStyle->iItalic)
		iTextStyle->iFontSpec.iFontStyle.SetPosture(EPostureItalic);
	else
		iTextStyle->iFontSpec.iFontStyle.SetPosture(EPostureUpright);
	
	HBufC* tmpFont = HBufC::New(iTextStyle->iFontSize.Length());
	CleanupStack::PushL(tmpFont);
	
	TPtr ptr = tmpFont->Des();
	ptr.Copy(iTextStyle->iFontSize);
	
	//���������С
	ptr.TrimAll();
	if(ptr.Right(1) == _L("%"))
		{
		TLex lex(ptr.Left(ptr.Length()-1));
		TInt size;
		lex.Val(size);
		iTextStyle->iFontSpec.iHeight = iTextStyle->iFontSpec.iHeight*size/100;
		}
	else if(ptr == _L("normal"))
		{
		iTextStyle->iFontSpec.iHeight = iTextStyle->iFontSpec.iHeight;
		}
	else if(ptr == _L("small"))
		{
		iTextStyle->iFontSpec.iHeight /= 2;
		}
	else if(ptr == _L("smaller"))
		{
		iTextStyle->iFontSpec.iHeight /= 3;
		}
	else if(ptr == _L("big"))
		{
		iTextStyle->iFontSpec.iHeight *= 2;
		}
	else if(ptr == _L("bigger"))
		{
		iTextStyle->iFontSpec.iHeight *= 3;
		}
	else
		{
		TLex lex(ptr);
		TInt size;
		lex.Val(size);
		iTextStyle->iFontSpec.iHeight = size;
		}
	
	CleanupStack::PopAndDestroy(1);
	
		
	}

CTextBlock* CTextBlock::CloneL()
	{
	CTextBlock* pBlock = CTextBlock::NewL(*iText);
	pBlock->iBlockRect = iBlockRect;
	pBlock->iTextStyle = iTextStyle;
	pBlock->iTextStyle->AddRef();
	
	return pBlock;
	}

void CTextBlock::SplitTextL(TextLineLink& aTextLineLink,TInt aWidth)
	{
	if(aWidth <= 0)
		return;
	
	if(aTextLineLink.GetCount() == 0)
		{
		SplitTextL(aTextLineLink,aWidth,0);
		}
	else
		{
		TextLine* lastLine = (TextLine*)aTextLineLink.GetRear();
		if(!lastLine)
			return;
		
		TRect rcLastLine = lastLine->GetLineRect();
		TInt desWidth = 0;
		TInt desHeight = 0;
		TInt startPos = 0;
		TInt endPos = 0;
		
		if(rcLastLine.Width() < aWidth)
			{
			TInt leftWidth = aWidth - rcLastLine.Width();
			
			endPos = GetSubStrByWidth(startPos,leftWidth,EFalse,desWidth,desHeight);
			CTextBlock* pBlock = CloneSubStrL(startPos,endPos,desWidth,desHeight);
			if(pBlock)
				{
				lastLine->PushL(pBlock);
				}
			
			startPos = endPos;
			endPos = GetSubStrByWidth(startPos,leftWidth,EFalse,desWidth,desHeight);
			}
		
		if(endPos != startPos)
			{
			SplitTextL(aTextLineLink,aWidth,startPos);
			}
		
		}
	}

void CTextBlock::SplitTextL(TextLineLink& aTextLineLink,TInt aWidth,TInt aOriginStartPos)
	{
	TInt desWidth = 0;
	TInt desHeight = 0;
	TInt startPos = aOriginStartPos;
	TInt endPos = GetSubStrByWidth(startPos,aWidth,ETrue,desWidth,desHeight);
	while(endPos != startPos)
		{
		TextLine* line = TextLine::NewLC();
		CTextBlock* pBlock = CloneSubStrL(startPos,endPos,desWidth,desHeight);
		line->PushL(pBlock);			
		
		aTextLineLink.PushL(line);
		CleanupStack::Pop(line);
		
		startPos = endPos;
		endPos = GetSubStrByWidth(startPos,aWidth,ETrue,desWidth,desHeight);
		}
	
	}

//传入起始位置，传出结束位置
//isNewLine 如果是新行，则至少容纳一个字符，如果不是新行，则直接换行如果字符长度超过aWidth
TInt CTextBlock::GetSubStrByWidth(TInt aBegin,TInt aWidth,TBool isNewLine,TInt& desWidth,TInt& desHeight)
{
	if(!iTextStyle->iFont)
		{
		CreateFontSpecByStyleL();
		CEikonEnv::Static()->ScreenDevice()->GetNearestFontInTwips( iTextStyle->iFont, iTextStyle->iFontSpec );
		}

	desHeight = iTextStyle->iFont->FontMaxHeight();

	TInt endPos = aBegin;
	TInt lineLength = 0;
	TInt tt = iText->Length();
	for(TInt i = aBegin; i < iText->Length(); i++)
		{
		TChar chr = (*iText)[i];
		TInt chrWidth = iTextStyle->iFont->CharWidthInPixels(chr);
		if(lineLength + chrWidth > aWidth)
			{
			if(endPos == aBegin && isNewLine)
				{
				desWidth = chrWidth;
				return aBegin+1;
				}
			else if(endPos == aBegin && !isNewLine)
				{
				desWidth = 0;
				return aBegin;
				}
			else
				{
				desWidth = lineLength;
				return endPos;
				}
			}
		
		endPos++;
		lineLength += chrWidth;
		}
	
	desWidth = lineLength;
	return endPos;
}

void CTextBlock::SetSize(TInt aWidth,TInt aHeight)
{
	iBlockRect.SetWidth(aWidth);
	iBlockRect.SetHeight(aHeight);
}

void CTextBlock::SetLTPoint(TInt aLeft,TInt aTop)
	{
//	iBlockRect.iTl.iX = aLeft;
//	iBlockRect.iTl.iY = aTop;
	
	iBlockRect.Move(aLeft,aTop);
	}

TRect CTextBlock::GetBlockRect() const
{
	return iBlockRect;
}

CTextBlock* CTextBlock::CloneSubStrL(TInt aBegin,TInt aEnd,TInt aWidth,TInt aHeight)
{
	if(aBegin == aEnd)
		return NULL;

	TPtrC ptr = iText->Mid(aBegin,aEnd-aBegin);
	CTextBlock* pBlock = CTextBlock::NewLC(ptr);
	pBlock->iTextStyle = iTextStyle;
	pBlock->iTextStyle->AddRef();
	pBlock->SetSize(aWidth,aHeight);
	CleanupStack::Pop(pBlock);
	
	return pBlock;
}